package com.analysis.client;

import com.analysis.config.CommonConstant;
import com.analysis.dto.AiCallResponse;
import com.analysis.dto.Reference;
import com.analysis.utils.ParseTextUtils;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import java.time.Duration;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;

/**
 * DeepSeek AI 高可用客户端
 * 基于 DeepSeek API 文档实现：https://api-docs.deepseek.com/zh-cn/api/create-chat-completion
 */
@Component
public class DeepseekAIChatClient {

    private static final Logger logger = LoggerFactory.getLogger(DeepseekAIChatClient.class);
    private static final Logger aiModelLogger = LoggerFactory.getLogger("com.analysis.client");

    @Autowired
    private RestTemplate restTemplate;

    @Value("${deepseek.chat.api-key}")
    private String apiKey;

    @Value("${deepseek.chat.base-url:https://api.deepseek.com}")
    private String baseUrl;

    @Value("${deepseek.chat.connect-timeout:300000}")
    private int connectTimeout;

    @Value("${deepseek.chat.read-timeout:300000}")
    private int readTimeout;

    @Value("${deepseek.chat.max-retries:2}")
    private int maxRetries;

    @Value("${deepseek.chat.base-delay-ms:1000}")
    private long baseDelayMs;

    @Value("${deepseek.chat.max-delay-ms:10000}")
    private long maxDelayMs;

    private final ObjectMapper objectMapper = new ObjectMapper();
    private final Random random = new Random();


    /**
     * 调用 DeepSeek API 进行对话补全
     *
     * @param question 用户问题
     * @return AI 响应结果
     */
    public AiCallResponse callQuestion(String question) {
        return callQuestionWithRetry(question + CommonConstant.QUESTION_SIZE, maxRetries);
    }

    /**
     * 带重试机制的调用方法
     */
    public AiCallResponse callQuestionWithRetry(String question, int maxRetries) {
        Exception lastException = null;
        for (int attempt = 1; attempt <= maxRetries; attempt++) {
            try {
                aiModelLogger.info("第{}次尝试调用 DeepSeek API - 问题: {}", attempt, question);

                DeepSeekRequest request = buildRequest(question);
                DeepSeekResponse response = callDeepSeekAPI(request);

                if (response != null && response.choices != null && !response.choices.isEmpty()) {
                    return processResponse(response, question);
                }
            } catch (Exception e) {
                lastException = e;
                aiModelLogger.warn("第{}次 DeepSeek API 调用失败 - 错误: {}", attempt, e.getMessage());
                if (attempt < maxRetries) {
                    long delay = calculateBackoffDelay(attempt);
                    aiModelLogger.info("等待 {}ms 后进行第{}次重试", delay, attempt + 1);
                    try {
                        Thread.sleep(delay);
                    } catch (InterruptedException ie) {
                        Thread.currentThread().interrupt();
                        throw new RuntimeException("DeepSeek API 重试被中断", ie);
                    }
                }
            }
        }
        aiModelLogger.error("DeepSeek API 调用最终失败 - 已重试{}次, 最后错误: {}", maxRetries,
                lastException != null ? lastException.getMessage() : "未知错误");
        return createErrorResponse(lastException);
    }

    /**
     * 信息源分析
     */
    public List<Reference> calReference(String query) {
        String question = callReference("列出你为回答“" + query + "”所提供的内容所参考和引用的信息源, 返回信息源的title和url", maxRetries);

        return ParseTextUtils.parseReferences(question);
    }


    /**
     * 带重试机制的调用方法
     */
    private String callReference(String question, int maxRetries) {
        Exception lastException = null;
        for (int attempt = 1; attempt <= maxRetries; attempt++) {
            try {
                aiModelLogger.info("第{}次尝试调用 DeepSeek API - 问题: {}", attempt, question);

                DeepSeekRequest request = buildRequest(question);
                DeepSeekResponse response = callDeepSeekAPI(request);

                if (response != null && response.choices != null && !response.choices.isEmpty()) {
                    return processResponse(response);
                }

            } catch (Exception e) {
                lastException = e;
                aiModelLogger.warn("第{}次 DeepSeek API 调用失败 - 错误: {}", attempt, e.getMessage());

                if (attempt < maxRetries) {
                    long delay = calculateBackoffDelay(attempt);
                    aiModelLogger.info("等待 {}ms 后进行第{}次重试", delay, attempt + 1);
                    try {
                        Thread.sleep(delay);
                    } catch (InterruptedException ie) {
                        Thread.currentThread().interrupt();
                        throw new RuntimeException("DeepSeek API 重试被中断", ie);
                    }
                }
            }
        }
        aiModelLogger.error("DeepSeek API 调用最终失败 - 已重试{}次, 最后错误: {}", maxRetries,
                lastException != null ? lastException.getMessage() : "未知错误");
        return null;
    }

    /**
     * 构建 DeepSeek API 请求
     */
    private DeepSeekRequest buildRequest(String question) {
        DeepSeekRequest request = new DeepSeekRequest();
        request.model = "deepseek-chat";
        request.messages = Arrays.asList(
                new Message("user", question)
        );
        request.temperature = 0.2;
        request.maxTokens = 1000;
        request.stream = false;
        return request;
    }

    /**
     * 调用 DeepSeek API
     */
    private DeepSeekResponse callDeepSeekAPI(DeepSeekRequest request) {
        String url = baseUrl + "/chat/completions";

        // 验证 API 密钥
        if (apiKey == null || apiKey.trim().isEmpty()) {
            throw new RuntimeException("DeepSeek API 密钥未配置或为空");
        }

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.setBearerAuth(apiKey);
        headers.set("User-Agent", "DeepSeek-AI-Client/1.0");

        HttpEntity<DeepSeekRequest> entity = new HttpEntity<>(request, headers);

        long startTime = System.currentTimeMillis();
        try {
            ResponseEntity<DeepSeekResponse> response = restTemplate.exchange(
                    url, HttpMethod.POST, entity, DeepSeekResponse.class);

            long duration = System.currentTimeMillis() - startTime;
            aiModelLogger.info("DeepSeek API 调用成功 - 耗时: {}ms, 状态码: {}",
                    duration, response.getStatusCode());

            System.err.println("deepseek消耗token：" + response.getBody().getUsage().getTotal_tokens());
            return response.getBody();
        } catch (Exception e) {
            long duration = System.currentTimeMillis() - startTime;
            aiModelLogger.error("DeepSeek API 调用失败 - 耗时: {}ms, 错误: {}, API Key: {}...",
                    duration, e.getMessage(),
                    apiKey.length() > 10 ? apiKey.substring(0, 10) + "..." : apiKey);
            throw e;
        }
    }

    /**
     * 处理 API 响应
     */
    private AiCallResponse processResponse(DeepSeekResponse response, String question) {
        AiCallResponse aiResponse = new AiCallResponse();

        if (response.choices != null && !response.choices.isEmpty()) {
            Choice choice = response.choices.get(0);
            if (choice.message != null && choice.message.content != null) {
                String content = choice.message.content;
                aiResponse.setText(content);
                aiResponse.setContents(ParseTextUtils.parseDeepseekText(content));
            }
        }

        return aiResponse;
    }

    /**
     * 处理 API 响应
     */
    private String processResponse(DeepSeekResponse response) {
        if (response.choices != null && !response.choices.isEmpty()) {
            Choice choice = response.choices.get(0);
            if (choice.message != null && choice.message.content != null) {
                return choice.message.content;
            }
        }
        return null;
    }


    /**
     * 创建错误响应
     */
    private AiCallResponse createErrorResponse(Exception exception) {
        AiCallResponse response = new AiCallResponse();
        response.setText("抱歉，DeepSeek AI 服务暂时不可用，请稍后重试。");
        response.setContents(Arrays.asList("服务暂时不可用"));
        return response;
    }

    /**
     * 计算退避延迟时间
     */
    private long calculateBackoffDelay(int attempt) {
        long delay = baseDelayMs * (1L << (attempt - 1)); // 指数退避
        delay += random.nextInt(1000); // 添加随机抖动
        return Math.min(delay, maxDelayMs);
    }

    /**
     * 异步调用方法
     */
    public CompletableFuture<AiCallResponse> callQuestionAsync(String question) {
        return CompletableFuture.supplyAsync(() -> callQuestion(question));
    }

    /**
     * 带超时的异步调用
     */
    public CompletableFuture<AiCallResponse> callQuestionWithTimeout(String question, Duration timeout) {
        return callQuestionAsync(question)
                .orTimeout(timeout.toMillis(), TimeUnit.MILLISECONDS);
    }

    // ==================== 内部类定义 ====================

    /**
     * DeepSeek API 请求类
     */
    public static class DeepSeekRequest {
        public String model;
        public List<Message> messages;
        public Double temperature;
        public Integer maxTokens;
        public Boolean stream;
        public String stop;
        public Double topP;
        public Integer frequencyPenalty;
        public Integer presencePenalty;

        public String getModel() {
            return model;
        }

        public void setModel(String model) {
            this.model = model;
        }

        public List<Message> getMessages() {
            return messages;
        }

        public void setMessages(List<Message> messages) {
            this.messages = messages;
        }

        public Double getTemperature() {
            return temperature;
        }

        public void setTemperature(Double temperature) {
            this.temperature = temperature;
        }

        public Integer getMaxTokens() {
            return maxTokens;
        }

        public void setMaxTokens(Integer maxTokens) {
            this.maxTokens = maxTokens;
        }

        public Boolean getStream() {
            return stream;
        }

        public void setStream(Boolean stream) {
            this.stream = stream;
        }

        public String getStop() {
            return stop;
        }

        public void setStop(String stop) {
            this.stop = stop;
        }

        public Double getTopP() {
            return topP;
        }

        public void setTopP(Double topP) {
            this.topP = topP;
        }

        public Integer getFrequencyPenalty() {
            return frequencyPenalty;
        }

        public void setFrequencyPenalty(Integer frequencyPenalty) {
            this.frequencyPenalty = frequencyPenalty;
        }

        public Integer getPresencePenalty() {
            return presencePenalty;
        }

        public void setPresencePenalty(Integer presencePenalty) {
            this.presencePenalty = presencePenalty;
        }
    }

    /**
     * 消息类
     */
    public static class Message {
        public String role;
        public String content;
        public String name;

        public Message() {
        }

        public Message(String role, String content) {
            this.role = role;
            this.content = content;
        }

        public String getRole() {
            return role;
        }

        public void setRole(String role) {
            this.role = role;
        }

        public String getContent() {
            return content;
        }

        public void setContent(String content) {
            this.content = content;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }
    }

    /**
     * DeepSeek API 响应类
     */
    public static class DeepSeekResponse {
        public String id;
        public String object;
        public long created;
        public String model;
        public List<Choice> choices;
        public Usage usage;
        public String systemFingerprint;

        public String getId() {
            return id;
        }

        public String getObject() {
            return object;
        }

        public long getCreated() {
            return created;
        }

        public String getModel() {
            return model;
        }

        public List<Choice> getChoices() {
            return choices;
        }

        public Usage getUsage() {
            return usage;
        }

        public String getSystemFingerprint() {
            return systemFingerprint;
        }
    }

    /**
     * 选择项类
     */
    public static class Choice {
        public int index;
        public Message message;
        public String finishReason;
        public LogProbs logprobs;

        public int getIndex() {
            return index;
        }

        public void setIndex(int index) {
            this.index = index;
        }

        public Message getMessage() {
            return message;
        }

        public void setMessage(Message message) {
            this.message = message;
        }

        public String getFinishReason() {
            return finishReason;
        }

        public void setFinishReason(String finishReason) {
            this.finishReason = finishReason;
        }

        public LogProbs getLogprobs() {
            return logprobs;
        }

        public void setLogprobs(LogProbs logprobs) {
            this.logprobs = logprobs;
        }
    }

    /**
     * 使用情况类
     */
    public static class Usage {
        public int prompt_tokens;
        public int completion_tokens;
        public int total_tokens;

        public int getPrompt_tokens() {
            return prompt_tokens;
        }

        public void setPrompt_tokens(int prompt_tokens) {
            this.prompt_tokens = prompt_tokens;
        }

        public int getCompletion_tokens() {
            return completion_tokens;
        }

        public void setCompletion_tokens(int completion_tokens) {
            this.completion_tokens = completion_tokens;
        }

        public int getTotal_tokens() {
            return total_tokens;
        }

        public void setTotal_tokens(int total_tokens) {
            this.total_tokens = total_tokens;
        }
    }

    /**
     * 对数概率类
     */
    public static class LogProbs {
        public List<TokenLogProb> content;

        public List<TokenLogProb> getContent() {
            return content;
        }

        public void setContent(List<TokenLogProb> content) {
            this.content = content;
        }
    }

    /**
     * Token 对数概率类
     */
    public static class TokenLogProb {
        public String token;
        public double logprob;
        public int[] bytes;

        public String getToken() {
            return token;
        }

        public void setToken(String token) {
            this.token = token;
        }

        public double getLogprob() {
            return logprob;
        }

        public void setLogprob(double logprob) {
            this.logprob = logprob;
        }

        public int[] getBytes() {
            return bytes;
        }

        public void setBytes(int[] bytes) {
            this.bytes = bytes;
        }
    }
}
